<?php

namespace Admin\Controller;

use Think\Controller;
use Common\Model\AuthRuleModel;
use Common\Model\AuthGroupModel;

class CommonController extends Controller {

    public function _initialize() {

        define(UID, is_login());
        if (!UID) {
            $this->redirect("Public/login");
        }
        define(IS_ROOT, is_administrator());
        if (!IS_ROOT && C('ADMIN_ALLOW_IP')) {
            // 检查IP地址访问
            if (!in_array(get_client_ip(), explode(',', C('ADMIN_ALLOW_IP')))) {
                $this->error('403:禁止访问');
            }
        }
        // 检测系统权限
        if (!IS_ROOT) {
            $access = $this->accessControl();

            if (false === $access) {
                $this->error('403:禁止访问');
            } elseif (null === $access) {
                //检测访问权限
                $rule = strtolower(MODULE_NAME . '/' . CONTROLLER_NAME . '/' . ACTION_NAME);

                if (!$this->checkRule($rule, array('in', '1,2'))) {
                    $this->error('未授权访问!');
                } else {
                    // 检测分类及内容有关的各项动态权限
                    $dynamic = $this->checkDynamic();
                    if (false === $dynamic) {
                        $this->error('未授权访问!');
                    }
                }
            }
        }

        //先不考虑权限，获取所有菜单
        $this->assign('__MENU__', $this->getMenus());
    }

    /**
     * 检测是否是需要动态判断的权限
     * @return boolean|null
     *      返回true则表示当前访问有权限
     *      返回false则表示当前访问无权限
     *      返回null，则表示权限不明
     *
     * @author 朱亚杰  <xcoolcc@gmail.com>
     */
    protected function checkDynamic() {
        
    }

    final protected function accessControl() {
        $allow = C('ALLOW_VISIT');
        $deny = C('DENY_VISIT');
        $check = strtolower(CONTROLLER_NAME . '/' . ACTION_NAME);
        if (!empty($deny) && in_array_case($check, $deny)) {
            return false; //非超管禁止访问deny中的方法
        }
        if (!empty($allow) && in_array_case($check, $allow)) {
            return true;
        }
        return null; //需要检测节点权限
    }

    /**
     * 权限检测
     * @param string  $rule    检测的规则
     * @param string  $mode    check模式
     * @return boolean
     * @author 朱亚杰  <xcoolcc@gmail.com>
     */
    final protected function checkRule($rule, $type = AuthRuleModel::RULE_URL, $mode = 'url') {
        static $Auth = null;
        if (!$Auth) {
            $Auth = new \Think\Auth();
        }

        if (!$Auth->check($rule, UID, $type, $mode)) {
            return false;
        }
        return true;
    }

    /**
     * 获取控制器菜单数组,二级菜单元素位于一级菜单的'child'元素中
     * @author 林群伟  <278805354@qq.com>
     */
    public function getMenus($controller = CONTROLLER_NAME) {
        if (empty($menus)) {
            // 获取主菜单
            $where['pid'] = 0;
            $where['hide'] = 0;
            if (!C('DEVELOP_MODE')) { // 是否开发者模式
                $where['is_dev'] = 0;
            }
            //先获取顶级
            $menus['main'] = M('Menu')->where($where)->order('sort asc')->select();
            // 获取顶级下面菜单
            foreach ($menus['main'] as $key => $item) {
                if (!is_array($item) || empty($item['title']) || empty($item['url'])) {
                    $this->error('控制器基类$menus属性元素配置有误');
                }
                if (stripos($item['url'], MODULE_NAME) !== 0) {
                    $item['url'] = MODULE_NAME . '/' . $item['url'];
                }

                // 判断主菜单权限
                if (!IS_ROOT && !$this->checkRule($item['url'], AuthRuleModel::RULE_MAIN, null)) {
                    unset($menus['main'][$key]);
                    continue; //继续循环
                }
                //获取这个菜单下有几组
                $groups = M('Menu')->where("pid = {$item['id']}")->distinct(true)->field("`group`")->select();
                //echo  M('Menu')->getLastSql();

                if ($groups) {
                    $groups = array_column($groups, 'group');
                } else {
                    $groups = array();
                }


                //获取二级分类的合法url
                $where = array();
                $where['pid'] = $item['id'];
                $where['hide'] = 0;
                if (!C('DEVELOP_MODE')) { // 是否开发者模式
                    $where['is_dev'] = 0;
                }
                $second_urls = M('Menu')->where($where)->getField('id,url');

                if (!IS_ROOT) {
                    // 检测菜单权限
                    $to_check_urls = array();
                    foreach ($second_urls as $keyvvv => $to_check_url) {
                        if (stripos($to_check_url, MODULE_NAME) !== 0) {
                            $rule = MODULE_NAME . '/' . $to_check_url;
                        } else {
                            $rule = $to_check_url;
                        }
                        if ($this->checkRule($rule, AuthRuleModel::RULE_URL, null))
                            $to_check_urls[] = $to_check_url;
                    }
                }



                foreach ($groups as $g) {

                    $map = array('group' => $g);   //获取group 下面列表
                    if (isset($to_check_urls)) {
                        if (empty($to_check_urls)) {
                            // 没有任何权限
                            continue;
                        } else {
                            $map['url'] = array('in', $to_check_urls);
                        }
                    }
                    $map['pid'] = $item['id'];
                    $map['hide'] = 0;
                    if (!C('DEVELOP_MODE')) { // 是否开发者模式
                        $map['is_dev'] = 0;
                    }
                    //echo "<br>===<bR>";
                    //查询菜单下，组下菜单
                    $menuList = M('Menu')->where($map)->field('id,class_icon,pid,title,url,tip')->order('sort asc')->select();
                    //print_r($menuList);
                    if ($menuList) {  //查询数组不能为空
                        ///print_r(list_to_tree($menuList, 'id', 'pid', 'operater', $item['id']));
                        // echo "<br>===<bR>";
                        //放在菜单子菜单下
                        $menus["main"][$key]['child'][$g] = list_to_tree($menuList, 'id', 'pid', 'operater', $item['id']);
                    }
                }
            }
            //  exit;
        }

        //exit;
        return $menus;
    }

    /**
     * 通用分页列表数据集获取方法
     *
     *  可以通过url参数传递where条件,例如:  index.html?name=asdfasdfasdfddds
     *  可以通过url空值排序字段和方式,例如: index.html?_field=id&_order=asc
     *  可以通过url参数r指定每页数据条数,例如: index.html?r=5
     *
     * @param sting|Model  $model   模型名或模型实例
     * @param array        $where   where查询条件(优先级: $where>$_REQUEST>模型设定)
     * @param array|string $order   排序条件,传入null时使用sql默认排序或模型属性(优先级最高);
     *                              请求参数中如果指定了_order和_field则据此排序(优先级第二);
     *                              否则使用$order参数(如果$order参数,且模型也没有设定过order,则取主键降序);
     *
     * @param boolean      $field   单表模型用不到该参数,要用在多表join时为field()方法指定参数
     * @author 朱亚杰 <xcoolcc@gmail.com>
     *
     * @return array|false
     * 返回数据集
     */
    protected function lists($model, $where = array(), $order = '', $field = true) {
        $options = array();
        $REQUEST = (array) I('get.');
        if (is_string($model)) {
            $model = M($model);
        }

        $OPT = new \ReflectionProperty($model, 'options');
        $OPT->setAccessible(true);

        $pk = $model->getPk();
        if ($order === null) {
            //order置空
        } else if (isset($REQUEST['_order']) && isset($REQUEST['_field']) && in_array(strtolower($REQUEST['_order']), array('desc', 'asc'))) {
            $options['order'] = '`' . $REQUEST['_field'] . '` ' . $REQUEST['_order'];
        } elseif ($order === '' && empty($options['order']) && !empty($pk)) {
            $options['order'] = $pk . ' desc';
        } elseif ($order) {
            $options['order'] = $order;
        }
        unset($REQUEST['_order'], $REQUEST['_field']);

        if (empty($where)) {
            // $where  =   array('status'=>array('egt',0));
        }
        if (!empty($where)) {
            $options['where'] = $where;
        }
        $options = array_merge((array) $OPT->getValue($model), $options);
        $total = $model->where($options['where'])->count();

        if (isset($REQUEST['r'])) {
            $listRows = (int) $REQUEST['r'];
        } else {
            $listRows = C('LIST_ROWS') > 0 ? C('LIST_ROWS') : 10;
        }
        $page = new \Think\Page($total, $listRows, $REQUEST);
        // if($total>$listRows){
        $page->setConfig('theme', ' %UP_PAGE% %LINK_PAGE% %DOWN_PAGE%  %HEADER%');
        // }
        $p = $page->show();
        $this->assign('_page', $p ? $p : '');
        $this->assign('_total', $total);
        $options['limit'] = $page->firstRow . ',' . $page->listRows;

        $model->setProperty('options', $options);

        return $model->field($field)->select();
    }

    /**
     * 处理文档列表显示
     * @param array $list 列表数据
     * @param integer $model_id 模型id
     */
    protected function parseDocumentList($list, $model_id = null) {
        $model_id = $model_id ? $model_id : 1;
        $attrList = get_model_attribute($model_id, false, 'id,name,type,extra');
        // 对列表数据进行显示处理
        if (is_array($list)) {
            foreach ($list as $k => $data) {
                foreach ($data as $key => $val) {
                    if (isset($attrList[$key])) {
                        $extra = $attrList[$key]['extra'];
                        $type = $attrList[$key]['type'];
                        if ('select' == $type || 'checkbox' == $type || 'radio' == $type || 'bool' == $type) {
                            // 枚举/多选/单选/布尔型
                            $options = parse_field_attr($extra);
                            if ($options && array_key_exists($val, $options)) {
                                $data[$key] = $options[$val];
                            }
                        } elseif ('date' == $type) { // 日期型
                            $data[$key] = date('Y-m-d', $val);
                        } elseif ('datetime' == $type) { // 时间型
                            $data[$key] = date('Y-m-d H:i', $val);
                        }
                    }
                }
                $data['model_id'] = $model_id;
                $list[$k] = $data;
            }
        }
        return $list;
    }

    final protected function editRow($model, $data, $where, $msg) {
        $id = array_unique((array) I('id', 0));
        $id = is_array($id) ? implode(',', $id) : $id;
        //如存在id字段，则加入该条件
        $fields = M($model)->getDbFields();
        if (in_array('id', $fields) && !empty($id)) {
            $where = array_merge(array('id' => array('in', $id)), (array) $where);
        }

        $msg = array_merge(array('success' => '操作成功！', 'error' => '操作失败！', 'url' => '', 'ajax' => IS_AJAX), (array) $msg);
        if (M($model)->where($where)->save($data) !== false) {
            $this->success($msg['success'], $msg['url'], $msg['ajax']);
        } else {
            $this->error($msg['error'], $msg['url'], $msg['ajax']);
        }
    }
    protected  function changeFieldData($model, $where = array(),$data, $msg = array('success' => '操作成功！', 'error' => '操作失败！')){
         return $this->editRow($model, $data, $where, $msg);
    }
    /**
     * 禁用条目
     * @param string $model 模型名称,供D函数使用的参数
     * @param array  $where 查询时的 where()方法的参数
     * @param array  $msg   执行正确和错误的消息,可以设置四个元素 array('success'=>'','error'=>'', 'url'=>'','ajax'=>false)
     *                     url为跳转页面,ajax是否ajax方式(数字则为倒数计时秒数)
     *
     * @author 朱亚杰  <zhuyajie@topthink.net>
     */
    protected function forbid($model, $where = array(), $msg = array('success' => '状态禁用成功！', 'error' => '状态禁用失败！')) {
        $data = array('status' => 0);
        $this->editRow($model, $data, $where, $msg);
    }

    /**
     * 恢复条目
     * @param string $model 模型名称,供D函数使用的参数
     * @param array  $where 查询时的where()方法的参数
     * @param array  $msg   执行正确和错误的消息 array('success'=>'','error'=>'', 'url'=>'','ajax'=>false)
     *                     url为跳转页面,ajax是否ajax方式(数字则为倒数计时秒数)
     *
     * @author 朱亚杰  <zhuyajie@topthink.net>
     */
    protected function resume($model, $where = array(), $msg = array('success' => '状态恢复成功！', 'error' => '状态恢复失败！')) {
        $data = array('status' => 1);
        $this->editRow($model, $data, $where, $msg);
    }

    protected function delete($model, $where = array(), $msg = array('success' => '删除成功！', 'error' => '删除失败！')) {
        $data['status'] = -1;
        $this->editRow($model, $data, $where, $msg);
    }

}
